---
title: Report render lifecycle
summary: Builds and renders a report's xPression XML into document bytes, caching the result unless the caller requests an overwrite.
status: draft
owner: SAIF Documentation
last_reviewed: 2026-09-01
library: SAIF.Services.Printing
reference_type: embedded
operation_id: op-06-report-render-lifecycle
trigger: Caller invokes ReportBase.Render, directly or transitively via Print/Save
---

# Report render lifecycle

Builds a report's xPression data XML (via the overridable `Create`) and renders it into document bytes through xPression, caching the rendered bytes so repeat calls avoid another round trip unless the caller requests an overwrite. This is the core rendering operation that `Print` and `Save` both depend on.

| Field | Value |
| --- | --- |
| **Operation ID** | OP-06 |
| **Trigger** | `Render` invoked directly, or transitively via `Print`/`Save` |
| **Inputs** | `overwrite As Boolean = False`, `ReportPackage`, `OutputProfile`, report XML from `Create` |
| **Outputs** | `Boolean` success; populates `ReportFile` (private `m_reportFile`) as a side effect |
| **Primary components** | `ReportBase.Render`, `Create` (overridable), `clsSecurityPrincipal`, `clsPrint.previewDocument` |
| **Entry point** | `Public Function Render(Optional overwrite As Boolean = False) As Boolean` |

## Steps

1. If a rendered file is already cached (`m_reportFile` is not `Nothing`) and the caller did not request `overwrite`, the operation skips re-rendering entirely — `Create` and xPression are not invoked again — and returns `True` immediately ([BR-PRT-007](../business-rules.md#br-prt-007-render-result-caching)).
2. Otherwise (no cached file, or `overwrite` requested), calls the overridable `Create(overwrite)` to (re)build `m_reportXml`, which as a side effect clears `m_Errors`.
3. Checks that `m_reportXml` is not `Nothing` and `ReportPackage.Length > 0` before proceeding — a report can be rendered only when its XML document exists and a report package is assigned ([BR-PRT-008](../business-rules.md#br-prt-008-render-and-distribute-preconditions)).
   - If the precondition fails: no rendering occurs, and the operation falls through to `result = False` (the initial default) **without** adding an entry to `Errors` — this differs from the exception-catch path in step 6.
4. Resolves the default printer for the current `clsSecurityPrincipal`, selecting the Web platform when `_environmentService.IsWeb` is `True` and Windows otherwise, then sets `xPrint.Printer` to that value ([BR-PRT-009](../business-rules.md#br-prt-009-default-printer-and-security-platform-selection)).
5. Calls `xPrint.previewDocument(ReportPackage, m_reportXml.ToXpression, OutputProfile)`.
   - The XML serialization consumed here is produced by `ToXpression` on the report's `XDesignXDocument`.

     > **Origin**: The `ToXpression` serialization is implemented by [Build xPression XML](op-11-build-xpression-xml.md), which handles key propagation, XML escaping, and self-closing empty elements.
   - The preview call itself is the same operation documented as [Preview a document](op-01-preview-a-document.md), including its package-name normalization.

     > **Origin**: The `previewDocument` call is implemented by [Preview a document](op-01-preview-a-document.md).
6. Assigns the returned bytes to `m_reportFile` and sets `result = True`.
7. If any exception occurs anywhere in steps 2–6, it is caught, appended to `Errors` as `New ErrorDetail("An error occurred while rendering the report.", ex)`, and `result` remains `False` — the exception is never rethrown ([BR-PRT-010](../business-rules.md#br-prt-010-non-throwing-render-and-distribute-failures)).

## Process flow

```mermaid
flowchart TD
	Start([Render called]) --> Cached{"reportFile set<br>AND not overwrite?"}
	Cached -->|Yes| Ok1(["Return True<br>(cached, BR-PRT-007)"])
	Cached -->|No| Create["Create() rebuilds XML"]
	Create --> Pre{"xml set AND<br>package set?"}
	Pre -->|No| Fail(["Return False<br>(no error added)"])
	Pre -->|Yes| Platform["Resolve platform<br>Web/Windows"]
	Platform --> DefPrinter["Get default printer"]
	DefPrinter --> Preview["previewDocument<br>(→OP-01, ToXpression→OP-11)"]
	Preview --> Store["Store ReportFile"]
	Store --> Ok2(["Return True"])
	Create -.->|exception anywhere| Err["Add ErrorDetail"]
	Pre -.->|exception anywhere| Err
	Platform -.->|exception anywhere| Err
	Preview -.->|exception anywhere| Err
	Err --> Fail2(["Return False"])
```

## Failure and edge-case behavior

- Exceptions never propagate out of `Render`; callers must inspect `Errors` rather than rely on a thrown exception ([BR-PRT-010](../business-rules.md#br-prt-010-non-throwing-render-and-distribute-failures)).
- The precondition-failure path (step 3) is distinct from the exception-catch path (step 7): a failed precondition produces `False` silently with **no** `ErrorDetail` added, whereas an exception during rendering **does** add one. A caller inspecting only `Errors` could miss a precondition failure.
- `xPrint` (via the `IReport.xPrint` read-only property) lazily constructs `clsPrint` with its parameterless constructor (`New clsPrint()`), which internally resolves `AppGlobal.EnvironmentService` rather than propagating `ReportBase`'s own `_environmentService` — this directly affects the printer resolution performed in step 4.*

## Related documentation
- [Index](../index.md)
- [Overview](../overview.md)
- [Architecture](../architecture.md)
- [Dependencies](../dependencies.md)
- [Operations and processes](../operations-processes.md)
- [Business rules](../business-rules.md)
- [Configuration](../configuration.md)
- [API reference](../api/index.md)

> **Note:** Statements marked with * were inferred from code structure, naming conventions, or
> contextual evidence where direct confirmation was not available in source artifacts. Statements
> marked with ** could not be confirmed; treat as unknown until verified.

## Sources
- `SAIF.Services.Printing/Reporting/ReportBase.vb`
- `SAIF.Services.Printing/Reporting/IReport.vb`
